package com.wfs.myapp.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.wfs.myapp.common.ApiResult;
import com.wfs.myapp.entity.domain.User;
import com.wfs.myapp.entity.domain.bk.BkGroup;
import com.wfs.myapp.entity.domain.bk.BkGroupMember;
import com.wfs.myapp.entity.dto.req.bk.AddGroupReqDto;
import com.wfs.myapp.entity.dto.req.bk.ApproveReqDto;
import com.wfs.myapp.entity.dto.req.bk.GenerateTalkRecordReqDto;
import com.wfs.myapp.entity.dto.req.bk.JoinGroupReqDto;
import com.wfs.myapp.entity.vo.GroupListVo;
import com.wfs.myapp.entity.vo.PageResponse;
import com.wfs.myapp.enums.GroupMemberStatusEnum;
import com.wfs.myapp.enums.ResponseCodeEnum;
import com.wfs.myapp.remote.wx.WxRemoteService;
import com.wfs.myapp.repository.UserRepository;
import com.wfs.myapp.repository.bk.GroupMemberRepository;
import com.wfs.myapp.repository.bk.GroupRepository;
import com.wfs.myapp.service.BkGroupService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class BkGroupServiceImpl implements BkGroupService {

    @Autowired
    private GroupRepository groupRepository;

    @Autowired
    private GroupMemberRepository groupMemberRepository;

    @Autowired
    private UserRepository userRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<?> addOrUpdate(Long userId, AddGroupReqDto addGroupReqDto) {
        BkGroup group;
        GroupListVo groupListVo = new GroupListVo();
        GroupListVo.GroupListMemberVo groupListMemberVo = new GroupListVo.GroupListMemberVo();
        if (Objects.nonNull(addGroupReqDto.getId())) {
            // 修改
            Optional<BkGroup> byId = groupRepository.findById(addGroupReqDto.getId());
            if (!byId.isPresent()) return ApiResult.error(ResponseCodeEnum.GROUP_NOT_EXIST);
            group = byId.get();
            BeanUtils.copyProperties(addGroupReqDto, group);
            group.setUpdatedTime(LocalDateTime.now());
            group.setUpdatedBy(String.valueOf(userId));
            group = groupRepository.save(group);
        } else {
            // 添加组
            group = new BkGroup();
            BeanUtils.copyProperties(addGroupReqDto, group);
            group.setMasterUserId(userId);
            group.setCreatedBy(String.valueOf(userId));
            group.setUpdatedBy(String.valueOf(userId));
            group = groupRepository.save(group);
            // 添加成员
            BkGroupMember groupMember = new BkGroupMember();
            groupMember.setGroupId(group.getId());
            groupMember.setUserId(userId);
            groupMember.setStatus(GroupMemberStatusEnum.APPROVE.getCode());
            groupMember.setUpdatedTime(LocalDateTime.now());
            groupMember.setUpdatedBy(String.valueOf(userId));
            groupMember.setCreatedBy(String.valueOf(userId));
            groupMemberRepository.save(groupMember);
            User user = userRepository.findById(userId).get();
            BeanUtils.copyProperties(groupMember, groupListMemberVo);
            groupListMemberVo.setNickname(user.getNickname());
            groupListMemberVo.setAvatar(user.getAvatar());
            groupListMemberVo.setGroupId(group.getId());
            BeanUtils.copyProperties(group, groupListVo);
            groupListVo.setMemberList(Arrays.asList(groupListMemberVo));
        }
        return ApiResult.success(groupListVo);
    }

    @Override
    public ApiResult<?> join(Long userId, JoinGroupReqDto joinGroupReqDto) {
        Long groupId = joinGroupReqDto.getGroupId();
        Optional<BkGroup> byId = groupRepository.findById(groupId);
        if (!byId.isPresent()) return ApiResult.error(ResponseCodeEnum.GROUP_NOT_EXIST);
        Optional<User> byId1 = userRepository.findById(joinGroupReqDto.getMemberId());
        if (!byId1.isPresent()) return ApiResult.error(ResponseCodeEnum.USER_NOT_EXIST);
        BkGroupMember byGroupIdAndUserId = groupMemberRepository.findByGroupIdAndUserId(joinGroupReqDto.getGroupId(), joinGroupReqDto.getMemberId());
        if (Objects.nonNull(byGroupIdAndUserId)) return ApiResult.error(ResponseCodeEnum.GROUP_MEMBER_EXIT);
        BkGroupMember groupMember = new BkGroupMember();
        BeanUtils.copyProperties(joinGroupReqDto, groupMember);
        groupMember.setUserId(joinGroupReqDto.getMemberId());
        groupMember.setCreatedBy(String.valueOf(userId));
        groupMember.setUpdatedBy(String.valueOf(userId));
        groupMember.setStatus(GroupMemberStatusEnum.PENDING.getCode());
        groupMemberRepository.save(groupMember);
        // response
        BkGroup group = byId.get();
        User masterUser = userRepository.findById(group.getMasterUserId()).get();
        GroupListVo groupListVo = new GroupListVo();
        BeanUtils.copyProperties(group, groupListVo);
        groupListVo.setMasterUserName(masterUser.getNickname());
        List<GroupListVo.GroupListMemberVo> groupMemberVoList = groupMemberRepository.findByGroupId(group.getId());
        groupListVo.setMemberList(groupMemberVoList);
        return ApiResult.success(groupListVo);
    }

    @Override
    public ApiResult<?> groupProcess(Long userId, ApproveReqDto joinGroupReqDto) {
        Optional<BkGroupMember> byId = groupMemberRepository.findById(joinGroupReqDto.getId());
        if (!byId.isPresent()) return ApiResult.error(ResponseCodeEnum.GROUP_MEMBER_NOT_EXIST);
        BkGroupMember groupMember = byId.get();
        groupMember.setStatus(joinGroupReqDto.getStatus());
        groupMember.setUpdatedBy(String.valueOf(userId));
        groupMember.setUpdatedTime(LocalDateTime.now());
        return ApiResult.success(groupMemberRepository.save(groupMember));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<?> delete(Long userId, JoinGroupReqDto joinGroupReqDto) {
        Long groupId = joinGroupReqDto.getGroupId();
        Optional<BkGroup> groupOpt = groupRepository.findById(groupId);
        if (!groupOpt.isPresent()) return ApiResult.error(ResponseCodeEnum.GROUP_NOT_EXIST);
        Optional<User> byId1 = userRepository.findById(joinGroupReqDto.getMemberId());
        if (!byId1.isPresent()) return ApiResult.error(ResponseCodeEnum.USER_NOT_EXIST);
        BkGroupMember groupMember = groupMemberRepository.findByGroupIdAndUserId(joinGroupReqDto.getGroupId(), joinGroupReqDto.getMemberId());
        if (Objects.isNull(groupMember)) return ApiResult.success("已删除");
        groupMemberRepository.deleteById(groupMember.getId());
        List<GroupListVo.GroupListMemberVo> memberVoList = groupMemberRepository.findByGroupId(groupId);
        if (CollectionUtils.isEmpty(memberVoList)) {
            groupRepository.deleteById(groupId);
            return ApiResult.success("已解散");
        }
        // 组长退出后 还有人则换组长
        BkGroup bkGroup = groupOpt.get();
        if (bkGroup.getMasterUserId().equals(joinGroupReqDto.getMemberId())) {
            GroupListVo.GroupListMemberVo groupListMemberVo = memberVoList.get(0);
            bkGroup.setMasterUserId(groupListMemberVo.getUserId());
            groupRepository.save(bkGroup);
        }


        return ApiResult.success("已删除");
    }

    @Override
    public ApiResult<?> groupList(Long myUserId, Long groupId, Integer page, Integer size) {
        long total = groupRepository.countAllPage();
        if (total == 0) return ApiResult.success(new PageResponse(new ArrayList(), total, page, size));
        List<GroupListVo> groupList = groupRepository.findAllPage(groupId, (page-1)*size, size);
        for (GroupListVo group : groupList) {
            group.setStatus(GroupMemberStatusEnum.PENDING.getCode());
            group.setStatusStr(GroupMemberStatusEnum.PENDING.getGroupMsg());
            List<GroupListVo.GroupListMemberVo> groupMemberVoList = groupMemberRepository.findByGroupId(group.getId());
            Optional<GroupListVo.GroupListMemberVo> myExistGroup = groupMemberVoList.stream().filter(member -> member.getUserId().equals(myUserId)).findFirst();
            myExistGroup.ifPresent(groupListMemberVo -> {
                group.setStatus(groupListMemberVo.getStatus());
                group.setStatusStr(GroupMemberStatusEnum.getGroupMsg(groupListMemberVo.getStatus()));
            });
            group.setMemberList(groupMemberVoList);
        }
        return ApiResult.success(new PageResponse(groupList, total, page, size));
    }

    @Override
    public ApiResult<List<GroupListVo>> getSameGroup(Long userId, Long myUserId) {
        List<GroupListVo> groupList = groupRepository.findByUserId(userId);
        List<GroupListVo> myGroupList = groupRepository.findByUserId(myUserId);
        List<GroupListVo> responseList = groupList.stream()
                .filter(myGroupList::contains)
                .collect(Collectors.toList());
        return ApiResult.success(responseList);
    }

    @Override
    public ApiResult<?> myGroupList(Long userId, Integer page, Integer size) {
        long total = groupRepository.countByMasterUserId(userId);
        if (total == 0) return ApiResult.success(new PageResponse(new ArrayList(), total, page, size));
        List<GroupListVo> groupList = groupRepository.findByMasterUserId(userId, (page-1)*size, size);
        for (GroupListVo group : groupList) {
            List<GroupListVo.GroupListMemberVo> groupMemberVoList = groupMemberRepository.findByGroupId(group.getId());
            group.setMemberList(groupMemberVoList);
        }
        return ApiResult.success(new PageResponse(groupList, total, page, size));
    }

    @Override
    public ApiResult<?> info(String groupId) {
        return null;
    }

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("id", "1");
        map.put("name", "asdjiol");
        System.out.println(JSONObject.toJSONString(map));
    }
}
